﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using nRoute.Components;
using nRoute.Mapping;
using nRoute.SiteMaps;
using nRoute.ViewModels;
using SimpleShell.Views;
using SimpleShell.Model;
using System.Runtime.Serialization;
using System.IO;
using System.Text;
using System.Xml;
using System.Windows;
using System.Xml.Serialization;

namespace SimpleShell.ViewModels
{
    [DefineNavigationContent("Content/Pages/Home/", typeof(Home))]
    [MapViewModel(typeof(Home))]
    public class HomeViewModel : NavigationViewModelBase
    {
        private const string PERSON_KEY = "_PERSON";

        private Person _person;
        private string _serializedPerson;

        public HomeViewModel()
        {
            SetupCommand();
            _person = new Person() { FirstName = "John", SecondName = "Doe", Age = 15 };
        }

#region Properties

        public Person CurrentPerson
        {
            get { return _person; }
            set
            {
                if (_person != value)
                {
                    _person = value;
                    NotifyPropertyChanged(() => CurrentPerson);
                }
            }
        }

        public string SerializedPerson
        {
            get { return _serializedPerson; }
            set
            {
                if (_serializedPerson != value)
                {
                    _serializedPerson = value;
                    NotifyPropertyChanged(() => SerializedPerson);
                }
            }
        }

        public ActionCommand SerializeCommand { get; private set; }

        public ActionCommand DeserializeCommand { get; private set; }

#endregion

#region Overrides

        protected override ParametersCollection OnSaveState()
        {
            return new ParametersCollection()
            {
                new Parameter(PERSON_KEY, this.CurrentPerson)
            };
        }

        protected override void OnRestoreState(ParametersCollection state)
        {
            this.CurrentPerson = state.GetValueOrDefault(PERSON_KEY, this.CurrentPerson);
        }

#endregion

#region Helpers

        private void SetupCommand()
        {
            SerializeCommand = new ActionCommand(() =>
            {
                if (this.CurrentPerson == null) return;    
                try
                {
                    this.SerializedPerson = SerializeWithXML<Person>(this.CurrentPerson);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            });

            DeserializeCommand = new ActionCommand(() =>
            {
                if (string.IsNullOrWhiteSpace(this.SerializedPerson)) return;
                try
                {
                    this.CurrentPerson = DeserializeWithXML<Person>(this.SerializedPerson);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            });
        }

        private string SerializeWithXML<T>(T value)
        {
            if (value == null) throw new ArgumentNullException("value");
            var _serializer = new XmlSerializer(typeof(T));
            var _stream = new MemoryStream();
            _serializer.Serialize(_stream, value);
            return Encoding.UTF8.GetString(_stream.GetBuffer(), 0, (int)_stream.Position);
        }

        private T DeserializeWithXML<T>(string text)
        {
            var _serializer = new XmlSerializer(typeof(T));
            var _stream = new MemoryStream(Encoding.UTF8.GetBytes(text));
            return (T)_serializer.Deserialize(_stream);
        }

        private string SerializeWithDCS<T>(T value)
        {
            if (value == null) throw new ArgumentNullException("value");
            var _serializer = new DataContractSerializer(typeof(T));
            var _stream = new MemoryStream();
            _serializer.WriteObject(_stream, value);
            return Encoding.UTF8.GetString(_stream.GetBuffer(), 0, (int)_stream.Position);
        }

        private T DeserializeWithDCS<T>(string text)
        {
            var _serializer = new DataContractSerializer(typeof(T));
            var _stream = new MemoryStream(Encoding.UTF8.GetBytes(text));
            return (T)_serializer.ReadObject(_stream);
        }

#endregion

    }
}